package net.entelijan.cobean.data.util;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


import org.jopendocument.model.OpenDocument;
import org.jopendocument.model.office.OfficeSpreadsheet;
import org.jopendocument.model.table.TableTable;
import org.jopendocument.model.table.TableTableCell;
import org.jopendocument.model.table.TableTableRow;
import org.jopendocument.sample.SpreadsheetReadToStdout;

public class ODSReader implements ITableReader {

	private String resource;

	private String tableName;

	public ODSReader() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.entelijan.data.literature.IReader#read(net.entelijan.data.literature
	 * .RowHandler)
	 */
	public void read(RowHandler rowHandler) throws IOException {
		final OpenDocument doc = new OpenDocument();
		if (resource == null) {
			throw new IllegalArgumentException("Missing property 'resource'");
		}
		URL url = SpreadsheetReadToStdout.class.getClassLoader().getResource(
				resource);
		if (url == null) {
			throw new IllegalArgumentException("Unknown resource '"
					+ this.resource + "'");
		}

		doc.loadFrom(url);
		List<OfficeSpreadsheet> officeSpreadsheets = doc.getBody()
				.getOfficeSpreadsheets();
		if (officeSpreadsheets.size() < 1) {
			throw new IllegalArgumentException("The spreadsheet '"
					+ this.resource + "' contains no 'officeSpreadsheet'");
		}
		OfficeSpreadsheet ss = officeSpreadsheets.get(0);

		TableTable t;
		if (this.tableName != null) {
			t = findTable(ss.getTables(), this.tableName);
			if (t == null) {
				throw new IllegalArgumentException("Found no table named '"
						+ this.tableName + "'");
			}
		} else {
			if (ss.getTables().size() < 1) {
				throw new IllegalStateException(
						"The spreadsheet contains no tables");
			} else {
				t = ss.getTables().get(0);
			}
		}

		int row = 0;
		ArrayList<ColDesc> colDescs = new ArrayList<ColDesc>();
		for (TableTableRow r : t.getRows()) {
			TableTableCell[] cellsInRange = r.getCellsInRange(0, 20);
			if (row == 0) {
				for (int col = 0; col < cellsInRange.length; col++) {
					TableTableCell c = cellsInRange[col];
					if (c != null) {
						colDescs.add(new ColDesc(col, c.getTextP()
								.getFullText()));
					}
				}
			} else {
				HashMap<String, String> ro = new HashMap<String, String>();
				for (ColDesc cd : colDescs) {
					TableTableCell c = cellsInRange[cd.getIndex()];
					ro.put(cd.getName(), c == null ? null
							: c.getTextP() == null ? null : c.getTextP()
									.getFullText());
				}
				rowHandler.handleRow(ro, row - 1);
			}
			row++;
		}
	}

	private TableTable findTable(List<TableTable> tables, String name) {
		TableTable re = null;
		for (TableTable table : tables) {
			if (name.equals(table.getTableName())) {
				re = table;
				break;
			}
		}
		return re;
	}

	private static class ColDesc {

		private int index;

		private String name;

		public ColDesc(int index, String name) {
			super();
			this.index = index;
			this.name = name;
		}

		public int getIndex() {
			return index;
		}

		public String getName() {
			return name;
		}

	}

	public String getResource() {
		return resource;
	}

	public void setResource(String resource) {
		this.resource = resource;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}
}
